<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 函数封装(简易工厂模式)  => 可以根据传入的参数,快速得到想要的对象
    // 缺点:
    // (1) 通过函数cat创建的对象,和函数本身并无任何关系 (Cat不是构造函数)
    // var arr = new Array(1, 2, 3);
    // console.log(arr instanceof Array);

    // var obj = new Object({ a: 1, b: 2 });
    // console.log(obj instanceof Object);

    // (2) 公共的属性和方法重复创建 =>占内存

    /* function cat(name, color) {
        var obj = { // new Object()
            name: name,
            color: color,
            species: "Cat",
            hall() {
                console.log("喵喵", "老吴");
            },
            skill() {
                console.log("捉老鼠", "卖萌");
            }
        }
        return obj;
    }


    var Tom = cat("Tom", "black");
    console.log(Tom);

    var Kitty = cat("Kitty", "pink");
    console.log(Kitty);

    var HongMao = cat("HongMao", "orange");
    console.log(HongMao);


    console.log(Tom instanceof cat, Tom instanceof Object);
    console.log(Kitty instanceof cat, Kitty instanceof Object);
    console.log(HongMao instanceof cat, HongMao instanceof Object); */
</script>
<script>


    // 自定义构造函数  
    function Cat(name, color) {
        //  {}
        //  this -> {}

        // 给创建的实力化对象绑定属性和方法
        // 实例化对象自己的属性
        this.name = name;
        this.color = color;

        // 公共的属性和方法重复创建   => 占内存
        // this.species = "Cat";
        // this.hall = function () {
        //     console.log("喵喵", "老吴");
        // }
        // this.skill = function () {
        //     console.log("捉老鼠", "卖萌");
        // }

        // return this;
    }


    // 公共的属性和方法重复创建   => 占内存?
    // 解决思路: 将 公共的属性和方法提取出来,单独存储,允许当前构造函数创建的所有实例化对象访问   => 存到哪?
    // (1) 存全局  => 不行,自当前脚本开始,均可以访问
    // (2) 存到构造函数上(函数也是一个特殊的实例化对象 => new Function(),可以在构造函数上存储数据如:Array.isArray  Promise.all)


    // 原型对象(prototype)
    // 构造函数上存在原型对象(prototype),官方提供,致力于将实例化对象中公共的属性和方法提取出来,单独存储,允许当前构造函数创建的所有实例化对象访问
    // Cat.prototype = {constructor}

    // console.dir(Cat); // 以键值对形式打印对象(函数也是一个特殊的实例化对象)的属性和方法


    Cat.prototype.species = "Cat";
    Cat.prototype.hall = function () {
        console.log("喵喵", "老吴");
    }
    Cat.prototype.skill = function () {
        console.log("捉老鼠", "卖萌");
    }

    // 此方法虽然存储在原型对象上(Cat.prototype),但是最终给构造函数Cat创建的实例化对象访问, 内部this指向调用此方法的实例化对象(所有的实例化对象均可以调用此方法,谁调用就指向谁)
    Cat.prototype.say = function () {
        // this -> this指向调用此方法的实例化对象
        console.log("this", this);
        console.log(this.name, this.color);
    }

    console.dir(Cat);
    // console.dir(Cat.prototype);

    // 如何访问构造函数原型对象(prototype)上的公共属性和方法?
    // (1) 实例化对象自己有,先访问自己的
    // (2) 实例化对象自己没有,则访问(创建该实例化对象的)构造函数的原型对象(prototype)


    var Tom = new Cat("Tom", "black");
    console.log(Tom);

    // console.log(Tom.name, Tom.color);

    // console.log(Tom.species);
    // console.log(Tom.hall);  // 取值
    // console.log(Tom.skill);
    // console.log(Tom.say);

    // Tom.hall(); // 取值 + 调用

    Tom.say(); //  取值 + 调用



    console.log("---------------------------------------------");

    var Kitty = new Cat("Kitty", "pink");
    console.log(Kitty);

    Kitty.say();

    // var HongMao = new Cat("HongMao", "orange");
    // console.log(HongMao);










</script>
<script>


</script>

</html>